home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / libcurses / v_maccur.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  46.2 KB  |  1,630 lines  |  [TEXT/R*ch]

  1. /*    File v_maccur.c:
  2.  *        Machine specific part of curses implementation for Macintosh.
  3.  *        Also includes rudimentary replacements for stdio functions.
  4.  *
  5.  *     Copyright (c) 1994
  6.  *    by Robert Zimmerman
  7.  *
  8.  *  This code may be included in any work, public or private, with the
  9.  *  exception of creating a commercial curses-compatible subroutine
  10.  *  library.  (In other words, use the code all you want, but please don't
  11.  *  rip off the author by reselling this code as your own).
  12.  *
  13.  */
  14.  
  15. #include <AppleEvents.h>
  16. #include <limits.h>
  17. #include <ctype.h>
  18. #include <stdarg.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <signal.h>
  22. #include "curses.h"
  23.  
  24. /****
  25. * Resources expected by this code are:
  26. *    An ALRT and DITL to put up alerts with the function maccur_cpu_share (see macro ALERT_RSRC_ID).
  27. *    A MENU and MBAR to draw the menu (which includes only the apple menu) (see macro MENU_RES_ID).
  28. *
  29. *    Optionally, an ALRT and DITL for the "About x..." menu item (see variable _maccur_about_res_id).
  30. ****/
  31.  
  32. /****
  33. * First some macros for font, screen setup, etc:
  34. ****/
  35.  
  36. #define X_MARGIN 2
  37. #define Y_MARGIN 4
  38. #define Y_PIX_WIN (rowheight_pix * _maccur_lines + Y_MARGIN)
  39. #define X_PIX_WIN (charwid_pix * _maccur_cols + 2 * X_MARGIN)
  40.  
  41. /****
  42. * ROW/COL_TO_PIX determine pen position to write character at row/col.
  43. * First row/column is 0/0.
  44. ****/
  45.  
  46. #define COL_TO_PIX(col) ((col) * charwid_pix + X_MARGIN)
  47. #define ROW_TO_PIX(row) (((row) + 1) * rowheight_pix)
  48.  
  49. #define MAX_OUT_STRSEG 132            /* Max number of parts of a single character row (distinguished by writing attrib. */
  50. #define MAX_TYPEAHEAD 32            /* Number of keystrokes that will be buffered. */
  51. #define FLASH_TICKS 8                /* Flash cursor 2x second. */
  52. #define WINDO_TOP_ON_SCREEN 40        /* Default position of window on screen. */
  53. #define WINDO_LEFT_ON_SCREEN 5
  54. #define ALERT_RSRC_ID 128            /* ALRT id for generalize alert. */
  55. #define MENU_RES_ID 128                /* MBAR id for putting up (not much of a) menu. */
  56.  
  57. #define TST_BIT(i, b) ((i) & (1 << (b)))
  58. #define SET_BIT(b) (1 << (b))
  59.  
  60. enum {
  61.     MACCUR_RETURN_ON_IDLE_BIT,
  62.     MACCUR_RETURN_ON_CHAR_BIT
  63. };
  64.  
  65. typedef struct key_evnt_strct {                /* Struct in which to buffer keyboard events. */
  66.     long msg;
  67.     short mod;
  68. } KEY_EVENT;
  69.  
  70. static KEY_EVENT typebuf[MAX_TYPEAHEAD];    /* Buffer for keyboard events. */
  71.  
  72. /****
  73. * The following can be modified before curses is initialized
  74. * in order to customize display, etc:
  75. ****/
  76.  
  77. int _maccur_cols = 80;                        /* Window will be initialized to this size. */
  78. int _maccur_lines = 25;
  79. char *_maccur_font_name = "Monaco";            /* Font to use (C string). */
  80. int _maccur_font_size = 9;                    /* Size of font. */
  81. int _maccur_handle_break_option = MACCUR_EXIT_ON_BREAK;    /* This determines what happens on CMD-. (see enum in macurses.h). */
  82. int _maccur_about_res_id = 128;                    /* Resource id alert to display if About... is chosen from apple menu. */
  83. char *_maccur_pgm_name = "Curses";            /* Program name for about and window title. */
  84. int _maccur_fg_sleep_ticks = 1;                /* How much can WaitNextEvent sleep in foreground. */
  85. int _maccur_bg_sleep_ticks = 2;                /* How much can WaitNextEvent sleep in background. */
  86. int _maccur_io_sleep_dvsr = 1;                /* How many of the output calls (maccur_printf, etc) call maccur_cpu_share. */
  87.                                             /*   (1/_maccur_io_sleep_dvsr of output calls will call maccur_cpu_share). */
  88.  
  89. static int rowheight_pix;                    /* Screen dimensions for each character. */
  90. static int charwid_pix;
  91. static short font_num;                        /* Writing font number. */
  92. static short font_res_id;                    /* Font resource ID. */
  93. static int show_cursor_flag;                /* TRUE if cursor should be flashed. */
  94. static Rect cursor_rect;                    /* Cursor, as a Rect. */
  95. static WindowPtr the_windo;                    /* Program window. */
  96. static long last_flash_when;                /* Keep track of when cursor flashed. */
  97. static int in_background_flag;                /* Keep track of program foreground/bkground state. */
  98. static int cursor_inverted;                    /* True if cursor is currently inverted. */
  99. static int typeahead_cnt;                    /* How many characters are waiting in typebuf. */
  100. static int typeahead_indx;                    /* Where does next character go in typebuf. */
  101. static int outchar_indx;                    /* Where does next character come out of typebuf. */
  102. static chtype *screen_char_arry;            /* Array holding screen contents. */
  103. static FontInfo fnt_info;                    /* Description of writing font. */
  104. static int maccur_about_mitm;                /* 1 if there is an About... item in apple menu. */
  105. static int maccur_has_menu;                    /* True if MBAR resource was found and menu put up. */
  106.  
  107. static int direct_curs_pos_row;                /* Keep track of cursor position when in direct (non-curses) mode. */
  108. static int direct_curs_pos_col;
  109.  
  110. static int cpu_share_rot_cnt;                /* When this reaches _maccur_io_sleep_dvsr its time to share CPU. */
  111.  
  112. /********
  113. **
  114. **    maccur_init_toolbox:  Initialize mac stuff.
  115. **
  116. **
  117. ********/
  118.  
  119. static void maccur_init_toolbox(void)
  120. {
  121.     InitGraf(&QD(thePort));
  122.     InitFonts();
  123.     FlushEvents(everyEvent, 0);
  124.     InitWindows();
  125.     InitMenus();
  126.     TEInit();
  127.     InitDialogs(0L);
  128.     InitCursor();
  129.     MaxApplZone();
  130. }
  131.  
  132. /********
  133. **
  134. **    event_do_nothing:  Do nothing in response to apple events.
  135. **
  136. **
  137. ********/
  138.  
  139. static pascal OSErr event_do_nothing(
  140. const AppleEvent *theAppleEvent,
  141. AppleEvent *reply,
  142. long refCon
  143. ) {
  144.     return 0;
  145. }
  146.  
  147. /********
  148. **
  149. **    quit_app:  Quit application in response to apple event.
  150. **        This is fairly severe -- Should put up a dialogue box?
  151. **
  152. **
  153. ********/
  154.  
  155. static pascal OSErr quit_app(
  156. const AppleEvent *theAppleEvent,
  157. AppleEvent *reply,
  158. long refCon
  159. ) {
  160.     ExitToShell();
  161.     return 0;
  162. }
  163.  
  164. /********
  165. **
  166. **    maccur_init_event: Initialize handlers (such as they are) for
  167. **        required apple events.
  168. **
  169. **
  170. ********/
  171.  
  172. static void maccur_init_event(void)
  173. {
  174.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  175.                     event_do_nothing, 0L, FALSE);
  176.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  177.                     event_do_nothing, 0L, FALSE);
  178.     AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
  179.                     event_do_nothing, 0L, FALSE);
  180.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  181.                     quit_app, 0L, FALSE);
  182. }
  183.  
  184. /********
  185. **
  186. **    maccur_get_font_info:  Search for resouce for desired font via FOND resource.
  187. **        Return dimension of characters for sizing of window.  There must be an
  188. **        easier way to determine the required window size b4 putting the window
  189. **        up (and without putting a fixed size window in resource file).
  190. **
  191. **    Returns:
  192. **        TRUE if font resource found, else FALSE.
  193. **
  194. **
  195. ********/
  196.  
  197. static int maccur_get_font_info(
  198. char *font_name,            /* -R- Name of desired font. */
  199. int font_pts,                /* -R- Size of desired font. */
  200. short *font_num_ptr,        /* -W- Return font number. */
  201. short *font_id_ptr,            /* -W- Return font resource id. */
  202. int *rowheight_pix_ptr,        /* -W- Return height of font. */
  203. int *charwid_pix_ptr        /* -W- Return width of font. */
  204. ) {
  205.     ResType res_typ;
  206.     Handle rsrc_ptr;
  207.     FamRec *fnt_fam_ptr;
  208.     FontAssoc *fnt_cnt_ptr;
  209.     AsscEntry *fnt_assc_list_ptr;
  210.     FontRec *fnt_rec_ptr;
  211.     int i;
  212.     char buf[256];
  213.  
  214.     memcpy(&res_typ, "FOND", sizeof(res_typ));
  215.     if ((rsrc_ptr = GetNamedResource(res_typ, (ConstStr255Param) font_name)) == NULL)
  216.         return FALSE;
  217.  
  218.     GetResInfo(rsrc_ptr, font_id_ptr, &res_typ, (unsigned char *) buf);
  219.     if (ResError() != noErr) return FALSE;
  220.  
  221.     fnt_fam_ptr = *((FamRec **)rsrc_ptr);
  222.     fnt_cnt_ptr = (FontAssoc *)(fnt_fam_ptr + 1);
  223.     fnt_assc_list_ptr = (AsscEntry *)(fnt_cnt_ptr + 1);
  224.  
  225.     *font_num_ptr = fnt_fam_ptr->ffFamID;
  226.  
  227.     for (i = 0; i < fnt_cnt_ptr->numAssoc + 1; i++)
  228.     {
  229.         if ((fnt_assc_list_ptr + i)->fontSize == font_pts &&
  230.                 (fnt_assc_list_ptr + i)->fontStyle == 0)
  231.             break;
  232.     }
  233.  
  234.     if (i == fnt_cnt_ptr->numAssoc + 1) return FALSE;
  235.  
  236.     fnt_rec_ptr = NULL;
  237.     if ((fnt_assc_list_ptr + i)->fontID == *font_id_ptr * 128 + font_pts)
  238.     {
  239.         memcpy(&res_typ, "FONT", sizeof(res_typ));
  240.         if ((rsrc_ptr = GetResource(res_typ, *font_id_ptr)) != NULL)
  241.             fnt_rec_ptr = *((FontRec **)rsrc_ptr);
  242.     }
  243.  
  244.     if (fnt_rec_ptr != NULL)
  245.     {
  246.         memcpy(&res_typ, "NFNT", sizeof(res_typ));
  247.         if ((rsrc_ptr = GetResource(res_typ, *font_id_ptr)) != NULL)
  248.             fnt_rec_ptr = *((FontRec **)rsrc_ptr);
  249.     }
  250.  
  251.     if (fnt_rec_ptr == NULL) return FALSE;
  252.  
  253.     *rowheight_pix_ptr = fnt_rec_ptr->fRectHeight;
  254.     *charwid_pix_ptr = fnt_rec_ptr->fRectWidth;
  255.  
  256.     return TRUE;
  257. }
  258.  
  259. /********
  260. **
  261. **    maccur_init_window: Size and open curses window.
  262. **
  263. **
  264. ********/
  265.  
  266. static void maccur_init_window(void)
  267. {
  268.     Rect windo_rect;
  269.     ResType font_res;
  270.     FontRec *fnt_rec_ptr;
  271.     Handle rsrc_ptr;
  272.     char windo_titl[128], font_name[32];
  273.  
  274.     font_name[0] = strlen(_maccur_font_name);                            /* Copy font name to local pascal string. */
  275.     strcpy(font_name + 1, _maccur_font_name);
  276.  
  277.     if (_maccur_font_size <= 0) _maccur_font_size = 9;                    /* Make sure font size is reasonable. */
  278.  
  279.     windo_rect.top = WINDO_TOP_ON_SCREEN;
  280.     windo_rect.left = WINDO_LEFT_ON_SCREEN;
  281.     if (maccur_get_font_info(font_name, _maccur_font_size,                /* Try to find font dimensions before putting up window. */
  282.                                 &font_num, &font_res_id,
  283.                                 &rowheight_pix, &charwid_pix))
  284.     {
  285.         windo_rect.bottom = windo_rect.top + Y_PIX_WIN;
  286.         windo_rect.right = windo_rect.left + X_PIX_WIN;
  287.     }
  288.     else
  289.     {
  290.         GetFNum((ConstStr255Param) font_name, &font_num);                /* If can't find them, put it up and then resize it. */
  291.         if (font_num == 0)
  292.         {
  293.             maccur_alert_msg("Could not access font '%s'!",
  294.                                 _maccur_font_name);
  295.             ExitToShell();
  296.         }
  297.         windo_rect.bottom = windo_rect.top + 10;
  298.         windo_rect.right = windo_rect.left + 10;
  299.     }
  300.  
  301.     strcpy(windo_titl, (_maccur_pgm_name == NULL ||
  302.                                 *_maccur_pgm_name == '\0') ?
  303.                                     "Curses" : _maccur_pgm_name);
  304.     if ((the_windo = NewWindow(nil, &windo_rect,
  305.                                 CtoPstr(windo_titl), TRUE,
  306.                                 noGrowDocProc, (WindowPtr)-1L,
  307.                                 FALSE, (long)nil)) == nil)
  308.     {
  309.         maccur_alert_msg("Could not initialize program window!");
  310.         ExitToShell();
  311.     }
  312.  
  313.     SetPort(the_windo);
  314.  
  315.     if (font_num != 0)
  316.         TextFont(font_num);
  317.  
  318.     TextSize(_maccur_font_size);
  319.     GetFontInfo(&fnt_info);
  320.     if (charwid_pix != fnt_info.widMax ||
  321.             rowheight_pix != fnt_info.ascent + fnt_info.descent + fnt_info.leading)
  322.     {
  323.         charwid_pix = fnt_info.widMax;
  324.         rowheight_pix = fnt_info.ascent + fnt_info.descent + fnt_info.leading;
  325.         SizeWindow(the_windo, X_PIX_WIN, Y_PIX_WIN, TRUE);
  326.     }
  327.  
  328.     /* Could check if bold-condense is same size as normal to allow/dissallow bold mode? */
  329.     ShowWindow(the_windo);
  330. }
  331.  
  332. /********
  333. **
  334. **    maccur_init_menus:  Set up menu bar (for now, only the apple menu).
  335. **
  336. **
  337. ********/
  338.  
  339. static void maccur_init_menus(void)
  340. {
  341.     Handle menu_bar_hndl;
  342.     MenuHandle menu_hndl;
  343.     char about_str[128];
  344.  
  345.     if ((menu_bar_hndl = GetNewMBar(MENU_RES_ID)) != NULL)
  346.     {
  347.         SetMenuBar(menu_bar_hndl);
  348.         menu_hndl = GetMHandle(MENU_RES_ID);
  349.         if (_maccur_about_res_id != 0)
  350.         {
  351.             sprintf(about_str, "About %s...", _maccur_pgm_name);
  352.             SetItem(menu_hndl, 1, CtoPstr(about_str));
  353.             maccur_about_mitm = 1;
  354.         }
  355.         else
  356.         {
  357.             DelMenuItem(menu_hndl, 1);
  358.             maccur_about_mitm = 0;
  359.         }
  360.         AddResMenu(menu_hndl, 'DRVR');
  361.  
  362.         DrawMenuBar();
  363.         maccur_has_menu = TRUE;
  364.     }
  365.     else maccur_has_menu = FALSE;
  366. }
  367.  
  368. /********
  369. **
  370. **    maccur_draw_text_line:  Write a single line of text to window.  Input text is
  371. **        type chtype, with attribute info.
  372. **
  373. **
  374. ********/
  375.  
  376. static void maccur_draw_text_line(
  377. chtype *line_ptr,        /* -R- Pointer to text to write. */
  378. int n,                    /* -R- Number of characters. */
  379. int row,                /* -R- Start at what row on screen (first row is 0). */
  380. int col                    /* -R- Start at what column on screen (first col is 0). */
  381. ) {
  382.     int i, first_pass_flag, j, attr, previous_attr, txt_face;
  383.     char out_str[MAX_OUT_STRSEG];
  384.  
  385.     SetPort(the_windo);
  386.  
  387.     MoveTo(COL_TO_PIX(col), ROW_TO_PIX(row));
  388.  
  389.     for (i = 0, first_pass_flag = TRUE; i < n; )                        /* Loop until string is written, writing it in segments */
  390.     {                                                                    /*   that all have the same attribute. */
  391.         for (j = 0, attr = (*(line_ptr + i) & A_ATTRIBUTES);
  392.                 i < n && j < MAX_OUT_STRSEG && attr == (*(line_ptr + i) & A_ATTRIBUTES);
  393.                 i++, j++)
  394.             out_str[j] = (*(line_ptr + i) & A_CHARTEXT);
  395.  
  396.         if (attr != previous_attr || first_pass_flag)                    /* Determine/set attribute for this segment... */
  397.         {
  398.             if (attr & A_REVERSE || attr & A_STANDOUT)                    /* Should do standout w/ hilite? */
  399.                 TextMode(notSrcCopy);
  400.             else
  401.                 TextMode(srcCopy);
  402.  
  403.             txt_face = normal;
  404.             if (attr & A_UNDERLINE)
  405.                 txt_face |= underline;
  406.  
  407.             if (attr & A_BOLD)                                            /* It is assument that bold condense is same size as normal. */
  408.                 txt_face |= (bold | condense);
  409.  
  410.             TextFace(txt_face);
  411.             previous_attr = attr;
  412.         }
  413.         DrawText(out_str, 0, j);
  414.         first_pass_flag = FALSE;
  415.     }
  416. }
  417.  
  418. /********
  419. **
  420. **    maccur_flash_cursor:  Flash cursor.
  421. **
  422. **
  423. ********/
  424.  
  425. static void maccur_flash_cursor(void)
  426. {
  427.     InvertRect(&cursor_rect);
  428.     cursor_inverted = !cursor_inverted;
  429. }
  430.  
  431. /********
  432. **
  433. **    maccur_unflash_cursor:  Unhighlight cursor if it is highlighted.
  434. **
  435. **
  436. ********/
  437.  
  438. static void maccur_unflash_cursor(void)
  439. {
  440.     if (cursor_inverted) maccur_flash_cursor();
  441. }
  442.  
  443. /********
  444. **
  445. **    maccur_set_cursor:  Set cursor_rect to reflect current cursor position.
  446. **        Before moving it, un-invert it if necessary (based on cursor_inverted flag).
  447. **
  448. **
  449. ********/
  450.  
  451. static void maccur_set_cursor(
  452. int row,        /* -R- Row for cursor. */
  453. int col            /* -R- Column for cursor. */
  454. ) {
  455.  
  456.     if (cursor_inverted) maccur_flash_cursor();
  457.     show_cursor_flag = TRUE;
  458.  
  459.     row = MIN(row, _maccur_lines - 1);
  460.     col = MIN(col, _maccur_cols - 1);
  461.  
  462.     cursor_rect.bottom = ROW_TO_PIX(row) + fnt_info.descent + fnt_info.leading;
  463.     cursor_rect.right = COL_TO_PIX(col + 1);
  464.     cursor_rect.top = cursor_rect.bottom - rowheight_pix;
  465.     cursor_rect.left = COL_TO_PIX(col);
  466.  
  467. }
  468.  
  469. /********
  470. **
  471. **    maccur_mouse_down_evnt:  Do something about mouse down event.  All that
  472. **        is handled is the apple menu, dragging the window, and system clicks.
  473. **
  474. **
  475. ********/
  476.  
  477. static void maccur_mouse_down_evnt(
  478. EventRecord *event_ptr        /* -R- The event details. */
  479. ) {
  480.     WindowPtr wndo_ptr;
  481.     MenuHandle apl_menu_hndl;
  482.     Str255 nam;
  483.     long menu_choice;
  484.     short wnd_part, menu_id, menu_itm, num;
  485.  
  486.     wnd_part = FindWindow(event_ptr->where, &wndo_ptr);
  487.     switch (wnd_part)
  488.     {
  489.         case inMenuBar:
  490.             if ((menu_choice = MenuSelect(event_ptr->where)) != 0)
  491.             {
  492.                 menu_id = HiWord(menu_choice);
  493.                 menu_itm = LoWord(menu_choice);
  494.  
  495.                 if (menu_id == MENU_RES_ID)
  496.                 {
  497.                     if (menu_itm == maccur_about_mitm)                    /* See if this is about... */
  498.                     {
  499.                         if (NoteAlert(_maccur_about_res_id, NULL) == -1)
  500.                             SysBeep(1);
  501.                     }
  502.                     else
  503.                     {
  504.                         apl_menu_hndl = GetMHandle(MENU_RES_ID);        /* If not, pass it on. */
  505.                         GetItem(apl_menu_hndl, menu_itm, nam);
  506.                         num = OpenDeskAcc(nam);
  507.                     }
  508.                 }
  509.                 HiliteMenu(0);
  510.             }
  511.             break;
  512.  
  513.         case inSysWindow:
  514.             SystemClick(event_ptr, wndo_ptr);
  515.             break;
  516.  
  517.         case inContent:
  518.             break;
  519.  
  520.         case inDrag:
  521.             DragWindow(wndo_ptr, event_ptr->where,
  522.                                 &QD(screenBits).bounds);
  523.             break;
  524.     }
  525. }
  526.  
  527. /********
  528. **
  529. **    maccur_event_loop: Main event loop.  Argument indicates whether it is to
  530. **        return due to a null event or due to a key stroke.
  531. **
  532. **    Returns:
  533. **        Reason for return (null or keystroke).
  534. **
  535. **
  536. ********/
  537.  
  538. static int maccur_event_loop(
  539. int until_flags
  540. ) {
  541.     EventRecord event;
  542.     int i;
  543.     long sleep;
  544.     char c;
  545.  
  546.     if (TST_BIT(until_flags, MACCUR_RETURN_ON_CHAR_BIT))                /* If waiting for a character, don't need a lot of CPU. */
  547.     {
  548.         if (in_background_flag)                                            /* Don't need any in background. */
  549.             sleep = LONG_MAX;
  550.         else sleep = FLASH_TICKS;                                        /* Just need enough to flash cursor in foreground. */
  551.     }
  552.     else                                                                /* If not waiting for a character, try to give up some time. */
  553.     {                                                                    /*   but maybe not a lot. */
  554.         if (in_background_flag)
  555.             sleep = _maccur_bg_sleep_ticks;
  556.         else sleep = _maccur_fg_sleep_ticks;
  557.     }
  558.  
  559.     while (1)                                                            /* Loop until return condition is met. */
  560.     {
  561.         if (WaitNextEvent(everyEvent, &event, sleep, nil))
  562.         {
  563.  
  564. #ifdef __MWERKS__
  565.           if (!SIOUXHandleOneEvent(&event)) {
  566. #endif
  567.  
  568.             switch (event.what)
  569.             {
  570.                 case kHighLevelEvent:
  571.                     AEProcessAppleEvent(&event);
  572.                     break;
  573.  
  574.                 case mouseDown:
  575.                     if (maccur_has_menu)
  576.                         maccur_mouse_down_evnt(&event);
  577.                     break;
  578.  
  579.                 case keyDown:
  580.                 case autoKey:
  581.                     if ((event.modifiers & cmdKey) != 0)                /* Ignore all command keys except CMD-. */
  582.                     {
  583.                         if ((event.message & charCodeMask) == '.')        /* This may exit right away or simulate a control-C interrupt. */
  584.                         {
  585.                             switch (_maccur_handle_break_option)
  586.                             {
  587.                                 case MACCUR_EXIT_ON_BREAK:
  588.                                     ExitToShell();
  589.                                     break;
  590.  
  591.                                 case MACCUR_SIGNAL_BREAK:
  592.                                     raise(SIGINT);
  593.                                     break;
  594.                             }
  595.                         }
  596.                         else break;
  597.                     }
  598.  
  599.                     if (typeahead_cnt >= MAX_TYPEAHEAD)                    /* Other keystrokes go into typeahead (if there is room). */
  600.                         SysBeep(1);                                        /* Typeahead buf is circular. */
  601.                     else
  602.                     {
  603.                         typebuf[typeahead_indx % MAX_TYPEAHEAD].msg = event.message;
  604.                         typebuf[typeahead_indx % MAX_TYPEAHEAD].mod = event.modifiers;
  605.                     }
  606.                     typeahead_indx++;
  607.                     typeahead_cnt++;
  608.  
  609.                     if (TST_BIT(until_flags, MACCUR_RETURN_ON_CHAR_BIT))/* Return if keystroke was what was wanted. */
  610.                         return MACCUR_RETURN_ON_CHAR_BIT;
  611.                     break;
  612.  
  613.                 case updateEvt:
  614.                     BeginUpdate((WindowPtr)(event.message));
  615.  
  616.                     EraseRect(&cursor_rect);                            /* This may be unnecessary??? */
  617.                     for (i = 0; i < _maccur_lines; i++)                    /* Redraw the screen. */
  618.                         maccur_draw_text_line(screen_char_arry + i * _maccur_cols,
  619.                                             _maccur_cols, i, 0);
  620.                     cursor_inverted = FALSE;
  621.  
  622.                     EndUpdate((WindowPtr)(event.message));
  623.                     break;
  624.  
  625.                 case osEvt:                                                /* Switch background/foreground. */
  626.                     if ((event.message & suspendResumeMessage) == resumeFlag)
  627.                         in_background_flag = FALSE;
  628.                     else
  629.                     {
  630.                         in_background_flag = TRUE;
  631.                         maccur_unflash_cursor();                        /* Turn cursor off in the background. */
  632.                     }
  633.                     break;
  634.  
  635.             }
  636. #ifdef __MWERKS__
  637.           }
  638. #endif
  639.         }
  640.         else if (TST_BIT(until_flags, MACCUR_RETURN_ON_IDLE_BIT))        /* If just letting CPU run, this is the cue to split. */
  641.             return MACCUR_RETURN_ON_IDLE_BIT;
  642.  
  643.         if (!in_background_flag && show_cursor_flag &&                    /* See if its time to flash the cursor. */
  644.                 event.when - last_flash_when > FLASH_TICKS)
  645.         {
  646.             if (event.what != osEvt)
  647.                 maccur_flash_cursor();
  648.             last_flash_when = event.when;
  649.         }
  650.     }
  651. }
  652.  
  653. /****
  654. * The following "keypad map" maps various non-ascii keystrokes to
  655. * their curses KEY_xxx equivalents.  This could be made global so
  656. * that user supplied replacements could be linked in (but who would
  657. * want to go to all that trouble).
  658. ****/
  659.  
  660. #define KEYMAP_BASE 0x33                                                /* Key number of first key to translate. */
  661. #define KEYMAP_TOP (KEYMAP_BASE + sizeof(dflt_keypad_map)/sizeof(KEYPAD_MAP))
  662. #define KEYMAP_NOCODE 0                                                    /* If this is key translation, return ascii code for that key. */
  663.  
  664. typedef struct keypad_map_strct {    /* Determine what to do with key/modifier: */
  665.     chtype basic_code;                /* This is translation of unmodified key. */
  666.     chtype shift_code;                /* Translation of key with shift. */
  667.     chtype opt_code;                /* Translation of key with option. */
  668.     chtype shift_opt_code;            /* Translation of key with shift-option. */
  669. } KEYPAD_MAP;
  670.  
  671. static KEYPAD_MAP dflt_keypad_map[] = {
  672. /* 33 delete */        {KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE},
  673. /* 34 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  674. /* 35 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  675. /* 36 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  676. /* 37 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  677. /* 38 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  678. /* 39 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  679. /* 3A */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  680. /* 3B */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  681. /* 3C */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  682. /* 3D */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  683. /* 3E */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  684. /* 3F */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  685. /* 40 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  686. /* 41 KP-. */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  687. /* 42 rt arrow (Mac +) */    {KEY_RIGHT, KEY_SRIGHT, KEYMAP_NOCODE, KEYMAP_NOCODE},
  688. /* 43 KP-* */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  689. /* 44 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  690. /* 45 KP-+ */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  691. /* 46 left arrow (Mac +) */    {KEY_LEFT, KEY_SLEFT, KEYMAP_NOCODE, KEYMAP_NOCODE},
  692. /* 47 clear */        {KEY_CLEAR, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  693. /* 48 down arrow (Mac +) */    {KEY_DOWN, KEY_NPAGE, KEY_END, KEYMAP_NOCODE},
  694. /* 49 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  695. /* 4A */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  696. /* 4B KP-/ */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  697. /* 4C enter */        {KEY_ENTER, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  698. /* 4D up arrow (Mac +) */    {KEY_UP, KEY_PPAGE, KEY_HOME, KEYMAP_NOCODE},
  699. /* 4E KP-- */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  700. /* 4F */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  701. /* 50 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  702. /* 51 KP-= */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  703. /* 52 KP-0 */        {KEYMAP_NOCODE, KEYMAP_NOCODE, KEY_F(0), KEY_F(10)},
  704. /* 53 KP-1 */        {KEY_C1, KEYMAP_NOCODE, KEY_F(1), KEY_F(11)},
  705. /* 54 KP-2 */        {KEY_DOWN, KEYMAP_NOCODE, KEY_F(2), KEY_F(12)},
  706. /* 55 KP-3 */        {KEY_C3, KEYMAP_NOCODE, KEY_F(3), KEY_F(13)},
  707. /* 56 KP-4 */        {KEY_LEFT, KEYMAP_NOCODE, KEY_F(4), KEY_F(14)},
  708. /* 57 KP-5 */        {KEY_B2, KEYMAP_NOCODE, KEY_F(5), KEY_F(15)},
  709. /* 58 KP-6 */        {KEY_RIGHT, KEYMAP_NOCODE, KEY_F(6), KEY_F(16)},
  710. /* 59 KP-7 */        {KEY_A1, KEYMAP_NOCODE, KEY_F(7), KEY_F(17)},
  711. /* 5A */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  712. /* 5B KP-8 */        {KEY_UP, KEYMAP_NOCODE, KEY_F(8), KEY_F(18)},
  713. /* 5C KP-9 */        {KEY_A3, KEYMAP_NOCODE, KEY_F(9), KEY_F(19)},
  714. /* 5D */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  715. /* 5E */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  716. /* 5F */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  717. /* 60 F5 */            {KEY_F(5), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  718. /* 61 F6 */            {KEY_F(6), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  719. /* 62 F7 */            {KEY_F(7), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  720. /* 63 F3 */            {KEY_F(3), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  721. /* 64 F8 */            {KEY_F(8), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  722. /* 65 F9 */            {KEY_F(9), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  723. /* 66 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  724. /* 67 F11 */        {KEY_F(11), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  725. /* 68 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  726. /* 69 F13 */        {KEY_F(13), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  727. /* 6A */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  728. /* 6B F14 */        {KEY_F(14), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  729. /* 6C */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  730. /* 6D F10 */        {KEY_F(10), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  731. /* 6E */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  732. /* 6F F12 */        {KEY_F(12), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  733. /* 70 */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  734. /* 71 F15 */        {KEY_F(15), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  735. /* 72 ins */        {KEY_IC, KEY_IL, KEYMAP_NOCODE, KEYMAP_NOCODE},
  736. /* 73 home */        {KEY_HOME, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  737. /* 74 pgup */        {KEY_PPAGE, KEY_SR, KEYMAP_NOCODE, KEYMAP_NOCODE},
  738. /* 75 fwd del */    {KEY_DC, KEY_DL, KEYMAP_NOCODE, KEYMAP_NOCODE},
  739. /* 76 F4 */            {KEY_F(4), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  740. /* 77 end */        {KEY_END, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  741. /* 78 F2 */            {KEY_F(2), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  742. /* 79 pgdn */        {KEY_NPAGE, KEY_SF, KEYMAP_NOCODE, KEYMAP_NOCODE},
  743. /* 7A F1 */            {KEY_F(1), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
  744. /* 7B left arrow */    {KEY_LEFT, KEY_SLEFT, KEYMAP_NOCODE, KEYMAP_NOCODE},
  745. /* 7C rt arrow */    {KEY_RIGHT, KEY_SRIGHT, KEYMAP_NOCODE, KEYMAP_NOCODE},
  746. /* 7D down arrow */    {KEY_DOWN, KEY_NPAGE, KEY_END, KEYMAP_NOCODE},
  747. /* 7E up arrow */    {KEY_UP, KEY_PPAGE, KEY_HOME, KEYMAP_NOCODE},
  748. /* 7F */            {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE}
  749. };
  750.  
  751. /********
  752. **
  753. **    maccur_key_trans:  Return curses key code based on keystroke event.
  754. **        If key has no entry in translation table, or entry is KEYMAP_NOCODE,
  755. **        return ascii value.
  756. **
  757. **    Returns:
  758. **        Character translation of keystroke (type chtype).
  759. **
  760. **
  761. ********/
  762.  
  763. static chtype maccur_key_trans(
  764. KEY_EVENT *ch_evnt_ptr,
  765. int keypad_enabled_flag
  766. ) {
  767.     chtype c, c_ascii, key;
  768.  
  769.     c_ascii = ch_evnt_ptr->msg & charCodeMask;
  770.     key = (ch_evnt_ptr->msg & keyCodeMask) >> 8;
  771.  
  772.     if (keypad_enabled_flag && key >= KEYMAP_BASE && key < KEYMAP_TOP)
  773.     {
  774.         if ((ch_evnt_ptr->mod & shiftKey) && (ch_evnt_ptr->mod & optionKey))
  775.             c = (dflt_keypad_map + (key - KEYMAP_BASE))->shift_opt_code;
  776.         else if ((ch_evnt_ptr->mod & shiftKey))
  777.             c = (dflt_keypad_map + (key - KEYMAP_BASE))->shift_code;
  778.         else if ((ch_evnt_ptr->mod & optionKey))
  779.             c = (dflt_keypad_map + (key - KEYMAP_BASE))->opt_code;
  780.         else
  781.             c = (dflt_keypad_map + (key - KEYMAP_BASE))->basic_code;
  782.  
  783.         if (c == KEYMAP_NOCODE) c = c_ascii;
  784.     }
  785.     else
  786.     {
  787.         if (key == 0x4C) c = '\n';                                        /* Give the keypad enter key a better ascii translation. */
  788.         else c = c_ascii;
  789.     }
  790.  
  791.     return c;
  792. }
  793.  
  794. /********
  795. **
  796. **    maccur_flush_typeahead:  Flush the typeahead buffer.
  797. **
  798. **
  799. ********/
  800.  
  801. void maccur_flush_typeahead(
  802. void
  803. ) {
  804.  
  805.     typeahead_indx = typeahead_cnt = outchar_indx = 0;
  806. }
  807.  
  808. /********
  809. **
  810. **    maccur_init: Entry point for initalization.  Sets LINES and COLS
  811. **        to the size of the window that is opened up.
  812. **
  813. **    Returns:
  814. **        TRUE if initialization is successful, else FALSE.
  815. **
  816. **
  817. ********/
  818.  
  819. bool maccur_init(void)
  820. {
  821.     int i, screen_chars;
  822.  
  823.     screen_chars = _maccur_cols * _maccur_lines;
  824.     if (screen_char_arry == NULL)                                        /* Allow for multiple calls to this routine (especially */
  825.     {                                                                    /*   implicit ones for fake stdio). */
  826.         maccur_init_toolbox();
  827.         maccur_init_event();
  828.         maccur_init_window();
  829.         maccur_init_menus();
  830.  
  831.         LINES = _maccur_lines;
  832.         COLS = _maccur_cols;
  833.  
  834.         if ((screen_char_arry = malloc(screen_chars * sizeof(chtype))) == NULL)
  835.             return FALSE;
  836.     }
  837.  
  838.     for (i = 0; i < screen_chars; i++)                                    /* Blank the screen. */
  839.         *(screen_char_arry + i) = ' ';
  840.  
  841.     return TRUE;
  842. }
  843.  
  844. /********
  845. **
  846. **    maccur_refresh: Refresh the screen for a curses window.
  847. **
  848. **    Returns:
  849. **        ERR on error, else OK.
  850. **
  851. **
  852. ********/
  853.  
  854. int maccur_refresh(WINDOW *win, bool outflag)
  855. {
  856.     static int    next_cursor_col = 0;        /* Save cursor position for next window refresh. */
  857.     static int    next_cursor_row = 0;        /*   (in case there are multiple calls before refresh and some have leaveok TRUE). */
  858.     static int window_current_flag;            /* Set to true when window is updated from saved image. */
  859.     static int cursor_enabled_flag;            /* Set to true if at least one window contributing to screen has a cursor. */
  860.     int i, mov_size, maxx, maxy;
  861.     chtype *src_ptr, *dst_ptr;
  862.                                                                         /* Your comment here                                       */
  863.  
  864.     if (screen_char_arry == NULL) return ERR;                            /* Initialization has not been done (bad). */
  865.  
  866.     if (win)                                                            /* If window was passed, transfer chars from it. */
  867.     {
  868.         if (win->_begy < _maccur_lines && win->_begx < _maccur_cols)
  869.         {
  870.             dst_ptr = screen_char_arry + (win->_begy * _maccur_cols) +
  871.                                 win->_begx;
  872.             if (win->_flags & _ISPAD)
  873.             {
  874.                 maxx = win->_pmap_maxx - win->_pmap_orgx;                /* For pads, get # rows and columns to display. */
  875.                 maxy = win->_pmap_maxy - win->_pmap_orgy;
  876.                 src_ptr = win->_y +                                        /* Point to 1st displayed character in pad. */
  877.                                 ((win->_pmap_orgy * win->_xdim) +
  878.                                 win->_pmap_orgx);
  879.             }
  880.             else
  881.             {
  882.                 maxx = win->_maxx;
  883.                 maxy = win->_maxy;
  884.                 src_ptr = win->_y;
  885.             }
  886.             mov_size = MIN(maxx, _maccur_cols - win->_begx) *
  887.                                 sizeof(chtype);
  888.             for (i = 0; i < maxy && i + win->_begy < _maccur_lines;        /* Copy text from window to screen image. */
  889.                                 i++, dst_ptr += _maccur_cols,
  890.                                     src_ptr += win->_xdim)
  891.                 memcpy(dst_ptr, src_ptr, mov_size); 
  892.         }
  893.  
  894.         if (!win->_leave)                                                /* If cursor is not left off, */
  895.         {
  896.             next_cursor_row = _CURS_CURSOR_SCREEN_ROW(win);                /* Save its position. */
  897.             next_cursor_col = _CURS_CURSOR_SCREEN_COL(win);
  898.             cursor_enabled_flag = TRUE;                                    /* It will be enabled on next screen update. */
  899.         }
  900.         else if (window_current_flag)                                    /* If this is 1st refresh after update and cursor */
  901.             cursor_enabled_flag = FALSE;                                /*   disabled, indicate that.  Subsequent refreshes */
  902.         else cursor_enabled_flag = cursor_enabled_flag || FALSE;        /*   or into flag so if cursor is enabled once it is shown. */
  903.         window_current_flag = FALSE;
  904.     }
  905.  
  906.     if (outflag)                                                        /* If actual screen update is to be done... */
  907.     {
  908.         for (i = 0; i < _maccur_lines; i++)                                /* Draw the characters. */
  909.             maccur_draw_text_line(screen_char_arry + i * _maccur_cols,
  910.                                 _maccur_cols, i, 0);
  911.         if (cursor_enabled_flag)
  912.         {
  913.             cursor_inverted = FALSE;                                    /* Window was completely re-written, so cursor is gone. */
  914.             maccur_set_cursor(next_cursor_row, next_cursor_col);
  915.         }
  916.         else show_cursor_flag = FALSE;
  917.         window_current_flag = TRUE;
  918.     }
  919.  
  920.     return OK;
  921. }
  922.  
  923. /********
  924. **
  925. **    maccur_end:  Exit curses mode.
  926. **
  927. **    Returns:
  928. **        OK.
  929. **
  930. **
  931. ********/
  932.  
  933. bool maccur_end(void)
  934. {
  935.     void maccur_noncurse_mode_scroll(void);
  936.  
  937.     maccur_noncurse_mode_scroll();                                        /* Scroll screen up a line and position cursor at bottom. */
  938.  
  939.     direct_curs_pos_row = _maccur_lines - 1;
  940.     direct_curs_pos_col = 0;
  941.  
  942.     maccur_set_cursor(direct_curs_pos_row, direct_curs_pos_col);
  943.     return OK;
  944. }
  945.  
  946. /********
  947. **
  948. **    maccur_beep: Beep or flash the screen.
  949. **
  950. **
  951. ********/
  952.  
  953. void maccur_beep(
  954. int flash_flag        /* -R- TRUE to flash instead of beep. */
  955. ) {
  956.     if (flash_flag)
  957.         SysBeep(0);
  958.     else
  959.         SysBeep(1);
  960. }
  961.  
  962. /********
  963. **
  964. **    maccur_kbinp: Take a single character input.
  965. **
  966. **    Returns:
  967. **        Character read, or ERR if no character ready or error.
  968. **
  969. **
  970. ********/
  971.  
  972. int maccur_kbinp(WINDOW *win, bool raw, bool cbreak)
  973. {
  974.  
  975.     if (typeahead_cnt == 0 && win->_nodelay)                            /* If caller is in a hurry don't make 'em wait */
  976.         return ERR;
  977.  
  978.     if (typeahead_cnt == 0)                                                /* If need to wait for input... */
  979.     {
  980.         maccur_set_cursor(_CURS_CURSOR_SCREEN_ROW(win),                    /* Set cursor to current input position. */
  981.                                 _CURS_CURSOR_SCREEN_COL(win));            /*   (this will also un-invert it). */
  982.         if (win->_leave)                                                /* If cursor is to be left off, set flag to false. */
  983.             show_cursor_flag = FALSE;
  984.         maccur_event_loop(SET_BIT(MACCUR_RETURN_ON_CHAR_BIT));
  985.     }
  986.  
  987.     if (typeahead_cnt > 0)                                                /* There should be something to return now, so do it... */
  988.     {
  989.         typeahead_cnt--;
  990.         if (outchar_indx >= MAX_TYPEAHEAD) outchar_indx = 0;
  991.         return maccur_key_trans(typebuf + outchar_indx++, win->_use_keypad);
  992.     }
  993.  
  994.     return ERR;
  995. }
  996.  
  997. /********
  998. **
  999. **    maccur_alert_text:  Display a string in an alert box.
  1000. **        Trim white space and newlines from beginning and end of string first.
  1001. **
  1002. **
  1003. ********/
  1004.  
  1005. static void maccur_alert_text(
  1006. char *txt
  1007. ) {
  1008.     static char buf[256];
  1009.     int len;
  1010.  
  1011.     while (isspace(*txt))                                                /* Strip off leading white space. */
  1012.         txt++;
  1013.     len = strlen(txt);
  1014.  
  1015.     while (len > 0 && isspace(*(txt + len - 1)))                        /* Strip off trailing white space. */
  1016.         len--;
  1017.     if (len > 255) len = 255;
  1018.  
  1019.     buf[0] = len;                                                        /* Make it a pascal string. */
  1020.     memcpy(buf + 1, txt, len);
  1021.  
  1022.     ParamText((ConstStr255Param) buf, NULL, NULL, NULL);
  1023.  
  1024.     if (CountResources('ALRT') == 0)
  1025.       return;
  1026.  
  1027.     Alert(ALERT_RSRC_ID, NULL);                                            /* Display as an alert. */
  1028. }
  1029.  
  1030. /********
  1031. **
  1032. **    maccur_alert_msg:  Display a string as an alert message, after
  1033. **        formatting it with sprintf.
  1034. **
  1035. **
  1036. ********/
  1037.  
  1038. void maccur_alert_msg(
  1039. char *fmt,
  1040. ...
  1041. ) {
  1042.     va_list args;
  1043.     int rtn;
  1044.  
  1045.     if (screen_char_arry == NULL)
  1046.         maccur_init();
  1047.  
  1048.     va_start(args, fmt);
  1049.     rtn = vsprintf(_curses_prntw, fmt, args);
  1050.     va_end(args);
  1051.  
  1052.     if (rtn < 0) strcpy(_curses_prntw, "Error in curses");
  1053.  
  1054.     maccur_alert_text(_curses_prntw);
  1055. }
  1056.  
  1057. /********
  1058. **
  1059. **    maccur_cpu_share:  Call the event manager so CPU time can be shared.
  1060. **
  1061. **
  1062. ********/
  1063.  
  1064. void maccur_cpu_share(void)
  1065. {
  1066.     maccur_event_loop(SET_BIT(MACCUR_RETURN_ON_IDLE_BIT));
  1067. }
  1068.  
  1069.  
  1070. /*    **************************************************************************    */
  1071. /*                                    STDIO emulation                                */
  1072. /*                                                                                */
  1073. /*    The following routines can be used to emulate standard io calls to stdin    */
  1074. /*    and stdout, placing the output in the curses window.                        */
  1075. /*                                                                                */
  1076. /*    **************************************************************************    */
  1077.  
  1078.  
  1079. /********
  1080. **
  1081. **    maccur_noncurse_mode_scroll: Scroll the screen up a line.
  1082. **
  1083. **
  1084. ********/
  1085.  
  1086. static void maccur_noncurse_mode_scroll(void)
  1087. {
  1088.     int i;
  1089.     chtype *scrn_ptr;
  1090.  
  1091.     memmove(screen_char_arry, screen_char_arry + _maccur_cols,                    /* Scroll it up. */
  1092.                                 _maccur_cols * (_maccur_lines - 1) * sizeof(chtype));
  1093.     scrn_ptr = screen_char_arry + ((_maccur_lines - 1) * _maccur_cols);
  1094.     for (i = 0; i < _maccur_cols; i++)                                            /* Clear bottom line. */
  1095.         *(scrn_ptr + i) = ' ';
  1096.  
  1097.     for (i = 0; i < _maccur_lines; i++)
  1098.         maccur_draw_text_line(screen_char_arry + i * _maccur_cols,
  1099.                                 _maccur_cols, i, 0);
  1100.     cursor_inverted = FALSE;
  1101. }
  1102.  
  1103. /********
  1104. **
  1105. **    maccur_noncurse_mode_show_str:  Display a string on the screen.
  1106. **        Wrap strings that are too long and expand tabs.
  1107. **
  1108. **
  1109. ********/
  1110.  
  1111. static void maccur_noncurse_mode_show_str(
  1112. char *str,                    /* -R- String to display. */
  1113. int *row_pos_ptr,            /* -M- Passed as row to start string, updated to row of end of string. */
  1114. int *col_pos_ptr,            /* -M- Passed as column to start string, updated to column of end of string. */
  1115. int *scroll_cnt_ptr,        /* -W- Return number of lines up the screen was scrolled. */
  1116. bool show_str_flag,            /* -R- TRUE to display string, FALSE to just return cursor position at end of string. */
  1117. bool add_newline_flag,        /* -R- True if extra newline should be added after string is displayed. */
  1118. bool clear_to_eos_flag        /* -R- True to clear all of screen following displayed string. */
  1119. ) {
  1120.     int nchars, char_pos, row_pos, col_pos, i, n_to_show,
  1121.         end_col_pos, move_down_flag;
  1122.     chtype *scrn_ptr;
  1123.     char *out_ptr, *cp;
  1124.  
  1125.     if (scroll_cnt_ptr != NULL)
  1126.         *scroll_cnt_ptr = 0;
  1127.     nchars = strlen(str);
  1128.     char_pos = 0;
  1129.     row_pos = *row_pos_ptr;
  1130.     col_pos = *col_pos_ptr;
  1131.     out_ptr = str;
  1132.  
  1133.     while (nchars > 0)                                                    /* Loop while there are characters to write out. */
  1134.     {
  1135.         if (col_pos >= _maccur_cols)
  1136.         {
  1137.             col_pos = 0;
  1138.             row_pos++;
  1139.         }
  1140.  
  1141.         if (show_str_flag && row_pos >= _maccur_lines)                    /* If writing position is past end of screen, scroll. */
  1142.         {
  1143.             maccur_noncurse_mode_scroll();
  1144.             if (scroll_cnt_ptr != NULL) (*scroll_cnt_ptr)++;
  1145.             row_pos = _maccur_lines - 1;
  1146.         }
  1147.  
  1148.         n_to_show = MIN(_maccur_cols - col_pos, nchars);                /* Determine how many chars to put in this line: */
  1149.         if ((cp = strchr(out_ptr, '\n')) != NULL)                        /*   up to end of line, up to end of string, */
  1150.             n_to_show = MIN(n_to_show, cp - out_ptr);                    /*   up to next newline, or up to tab. */
  1151.         if ((cp = strchr(out_ptr, '\t')) != NULL)
  1152.             n_to_show = MIN(n_to_show, cp - out_ptr);
  1153.  
  1154.         if (show_str_flag)
  1155.         {
  1156.             scrn_ptr = screen_char_arry + (row_pos * _maccur_cols) +
  1157.                                 col_pos;
  1158.             for (i = 0; i < n_to_show; i++)                                /* Copy the characters out. */
  1159.                 *(scrn_ptr + i) = *(out_ptr + i);
  1160.         }
  1161.         col_pos += n_to_show;
  1162.  
  1163.         move_down_flag = FALSE;
  1164.         if (*(out_ptr + n_to_show) == '\n')                                /* If newline encountered, blank out rest of line */
  1165.         {                                                                /*   and position to beginning of next. */
  1166.             if (show_str_flag)
  1167.             {
  1168.                 scrn_ptr = screen_char_arry + (row_pos * _maccur_cols);
  1169.                 while (col_pos < _maccur_cols)
  1170.                     *(scrn_ptr + col_pos++) = ' ';
  1171.             }
  1172.             n_to_show++;                                                /* Skip over the '\n' */
  1173.             move_down_flag = TRUE;
  1174.         }
  1175.         else if (*(out_ptr + n_to_show) == '\t')                        /* For a tab, blank up to the next tab stop. */
  1176.         {
  1177.             end_col_pos = col_pos + (_curses_tab_wid -                    /* Blank fwd until col_pos becomes multiple of tab wid. */
  1178.                                 col_pos % _curses_tab_wid);
  1179.             end_col_pos = MIN(end_col_pos, _maccur_cols);                /* But don't wrap over into next line. */
  1180.             if (show_str_flag)
  1181.             {
  1182.                 scrn_ptr = screen_char_arry + (row_pos * _maccur_cols);
  1183.                 while (col_pos < end_col_pos)
  1184.                     *(scrn_ptr + col_pos++) = ' ';
  1185.             }
  1186.             col_pos = end_col_pos;
  1187.             n_to_show++;                                                /* Skip over the '\t' */
  1188.         }
  1189.  
  1190.         if (show_str_flag)
  1191.             maccur_draw_text_line(screen_char_arry +                    /* Redraw the modified line. */
  1192.                                 row_pos * _maccur_cols,
  1193.                                 _maccur_cols, row_pos, 0);
  1194.  
  1195.         if (move_down_flag)
  1196.         {
  1197.             col_pos = 0;                                                /* Move to next line. */
  1198.             row_pos++;
  1199.         }
  1200.  
  1201.         if (show_str_flag && row_pos >= _maccur_lines)                    /* If writing position is past end of screen, scroll. */
  1202.         {
  1203.             maccur_noncurse_mode_scroll();
  1204.             if (scroll_cnt_ptr != NULL) (*scroll_cnt_ptr)++;
  1205.             row_pos = _maccur_lines - 1;
  1206.         }
  1207.  
  1208.         out_ptr += n_to_show;
  1209.         nchars -= n_to_show;
  1210.     }
  1211.  
  1212.     if (add_newline_flag || clear_to_eos_flag)                            /* If extra newline is to be added after string output or */
  1213.     {                                                                    /*   or screen is to be cleared up to end of screen. */
  1214.         if (show_str_flag)
  1215.         {
  1216.             int last_row, i_rw;
  1217.  
  1218.             if (clear_to_eos_flag)                                        /* Whether new line or cleareos, will be clearing rest */
  1219.                 last_row = _maccur_lines;                                /*   of current line and possibly others. */
  1220.             else last_row = row_pos + 1;
  1221.  
  1222.             for (i_rw = row_pos; i_rw < last_row; i_rw++)                /* Do next line or a bunch depending on clear_to_eos_flag. */
  1223.             {
  1224.                 scrn_ptr = screen_char_arry + (i_rw * _maccur_cols);
  1225.                 for (i = (i_rw == row_pos ? col_pos : 0);                /* Clear the line. */
  1226.                         i < _maccur_cols; i++)
  1227.                     *(scrn_ptr + i) = ' ';
  1228.  
  1229.                 maccur_draw_text_line(screen_char_arry +                /* Redraw the modified line. */
  1230.                                 i_rw * _maccur_cols,
  1231.                                 _maccur_cols, i_rw, 0);
  1232.             }
  1233.         }
  1234.  
  1235.         if (add_newline_flag)                                            /* If actually echoing a newline. */
  1236.         {
  1237.             col_pos = 0;
  1238.             row_pos++;
  1239.             if (show_str_flag && row_pos >= _maccur_lines)                /* Scroll of necessary. */
  1240.             {
  1241.                 maccur_noncurse_mode_scroll();
  1242.                 if (scroll_cnt_ptr != NULL) (*scroll_cnt_ptr)++;
  1243.                 row_pos = _maccur_lines - 1;
  1244.             }                                                            /* (this automatically clears the last line of screen). */
  1245.         }
  1246.     }
  1247.  
  1248.     *row_pos_ptr = row_pos;
  1249.     *col_pos_ptr = col_pos;
  1250. }
  1251.  
  1252. /********
  1253. **
  1254. **    maccur_noncurse_mode_getstr:  Input a string, echoing input to screen,
  1255. **        allowing editing with left/right arrows, delete key, clear key
  1256. **        (or ctrl-u) to clear input, ctrl-e to move to end of input,
  1257. **        ctrl-d to return EOF.  Special single character mode does away
  1258. **        with most special line editing, and returns with the single char (ala getchar).
  1259. **
  1260. **    Returns:
  1261. **        Number of characters in, or EOF if CTRL-D entered.
  1262. **
  1263. **
  1264. ********/
  1265.  
  1266. static int maccur_noncurse_mode_getstr(
  1267. char *str,                    /* -W- Put the string read here. */
  1268. int max_chars,                /* -R- Size of above string (or -1 if unknown). */
  1269. int single_char_flag        /* -R- True if this is call for a single character. */
  1270. ) {
  1271.     int begin_at, nchars, pos, key, c_ascii, cleareos_flag,
  1272.         redisplay_flag, disp_pos, disp_row, disp_col, scroll_cnt,
  1273.         rtn_val, string_ended_flag, add_newline_flag, save_char;
  1274.  
  1275.     begin_at = (direct_curs_pos_row * _maccur_cols) +                    /* Remember initial cursor position. */
  1276.                                 direct_curs_pos_col;
  1277.  
  1278.     nchars = pos = rtn_val = 0;
  1279.     *str = '\0';
  1280.     string_ended_flag = FALSE;
  1281.     while (!string_ended_flag)
  1282.     {
  1283.         redisplay_flag = FALSE;
  1284.         cleareos_flag = FALSE;
  1285.         add_newline_flag = FALSE;
  1286.  
  1287.         if (typeahead_cnt == 0)                                            /* If need to wait for input... */
  1288.         {
  1289.             disp_row = begin_at/_maccur_cols;
  1290.             disp_col = begin_at % _maccur_cols;
  1291.             save_char = *(str + pos);
  1292.             *(str + pos) = '\0';
  1293.             maccur_noncurse_mode_show_str(str,                            /* Measure string to determine cursor position at */
  1294.                                 &disp_row, &disp_col,                    /*   input point (there might be tabs). */
  1295.                                 NULL, FALSE, FALSE, FALSE);
  1296.             *(str + pos) = save_char;
  1297.  
  1298.             if (disp_col >= _maccur_cols)                                /* Move cursor to next line if it is past end of a line. */
  1299.             {
  1300.                 disp_col = 0;
  1301.                 disp_row++;
  1302.             }
  1303.  
  1304.             if (disp_row >= _maccur_lines)                                /* Scroll if cursor off screen. */
  1305.             {
  1306.                 maccur_noncurse_mode_scroll();
  1307.                 disp_row = _maccur_lines - 1;
  1308.                 begin_at -= _maccur_cols;
  1309.             }
  1310.  
  1311.             maccur_set_cursor(disp_row, disp_col);                        /* Set cursor to current input position. */
  1312.             maccur_event_loop(SET_BIT(MACCUR_RETURN_ON_CHAR_BIT));        /* Get some text. */
  1313.             maccur_unflash_cursor();
  1314.         }
  1315.  
  1316.         if (typeahead_cnt > 0)                                            /* There should be at least one keystroke available. */
  1317.         {
  1318.             typeahead_cnt--;
  1319.             if (outchar_indx >= MAX_TYPEAHEAD) outchar_indx = 0;
  1320.             c_ascii = (typebuf + outchar_indx)->msg & charCodeMask;
  1321.             key = ((typebuf + outchar_indx)->msg & keyCodeMask) >> 8;
  1322.             outchar_indx++;
  1323.  
  1324.             switch (key)                                                /* See if key has special meaning. */
  1325.             {
  1326.                 case 0x7D:                                                /* Up and down arrows (Mac plus and II). */
  1327.                 case 0x7E:                                                /* All ignored. */
  1328.                 case 0x4D:
  1329.                 case 0x48:
  1330.                     SysBeep(1);
  1331.                     break;
  1332.         
  1333.                 case 0x7C:                                                /* Right arrow (Mac II). */
  1334.                 case 0x42:                                                /*   (Mac plus). */
  1335.                     if (pos < nchars)
  1336.                         pos++;
  1337.                     else SysBeep(1);
  1338.  
  1339.                     break;
  1340.         
  1341.                 case 0x7B:                                                /* Left arrow (Mac II). */
  1342.                 case 0x46:                                                /*   (Mac plus). */
  1343.                     if (pos > 0)
  1344.                         pos--;
  1345.                     else SysBeep(1);
  1346.         
  1347.                     break;
  1348.  
  1349.                 case 0x33:                                                /* DELETE key. */
  1350.                     if (pos > 0)
  1351.                     {
  1352.                         if (pos < nchars)
  1353.                             memmove(str + (pos - 1), str + pos, nchars - pos);
  1354.                         *(str + --nchars) = '\0';
  1355.                         pos--;
  1356.                         redisplay_flag = TRUE;
  1357.                         cleareos_flag = TRUE;
  1358.                     }
  1359.                     else SysBeep(1);
  1360.  
  1361.                     break;
  1362.  
  1363.                 case 0x47:                                                /* CLEAR key. */
  1364.                     if (single_char_flag) SysBeep(1);                    /* Don't let getchar user think CLEAR means anything. */
  1365.                     nchars = pos = 0;
  1366.                     *str = '\0';
  1367.                     redisplay_flag = TRUE;
  1368.                     cleareos_flag = TRUE;
  1369.                     break;
  1370.  
  1371.                 case 0x24:                                                /* RETURN key. */
  1372.                 case 0x4C:                                                /* ENTER key. */
  1373.                     if (single_char_flag)                                /* Single character mode will allow \n as a return value. */
  1374.                     {
  1375.                         *str = '\n';
  1376.                         *(str + 1) = '\0';
  1377.                         nchars = 1;
  1378.                     }
  1379.                     else add_newline_flag = TRUE;                        /* Don't return newline in string, so set flag to echo it. */
  1380.                     string_ended_flag = TRUE;
  1381.                     redisplay_flag = TRUE;                                /* Redisplay it to echo newline. */
  1382.                     rtn_val = pos = nchars;
  1383.                     break;
  1384.         
  1385.                 default:
  1386.                     if (c_ascii == 4)                                    /* Control-D (return EOF). */
  1387.                     {
  1388.                         rtn_val = EOF;
  1389.                         string_ended_flag = TRUE;
  1390.                     }
  1391.                     else if (!single_char_flag && c_ascii == 5)            /* Control-E (move to end of input text). */
  1392.                     {
  1393.                         pos = nchars;
  1394.                     }
  1395.                     else if (!single_char_flag && c_ascii == 21)        /* Control-U (same as CLEAR) */
  1396.                     {
  1397.                         nchars = pos = 0;
  1398.                         *str = '\0';
  1399.                         redisplay_flag = TRUE;
  1400.                         cleareos_flag = TRUE;
  1401.                     }
  1402.                     else                                                /* Get here if its just a regular old ascii value. */
  1403.                     {
  1404.                         if (max_chars >= 0 && nchars >= max_chars - 1)
  1405.                             SysBeep(1);
  1406.                         else
  1407.                         {
  1408.                             if (pos < nchars)
  1409.                                 memmove(str + (pos + 1), str + pos, nchars - pos);
  1410.                             *(str + pos++) = c_ascii;
  1411.                             *(str + ++nchars) = '\0';
  1412.                             redisplay_flag = TRUE;
  1413.                         }
  1414.                     }
  1415.                     break;
  1416.             }
  1417.  
  1418.             if (redisplay_flag)                                            /* If something has happened necesitating a redraw, do it. */
  1419.             {
  1420.                 disp_pos = MAX(0, pos - 1);                                /* Just redraw from current position on. */
  1421.                 disp_row = begin_at/_maccur_cols;                        /* But first measure to find start position. */
  1422.                 disp_col = begin_at % _maccur_cols;
  1423.                 save_char = *(str + disp_pos);
  1424.                 *(str + disp_pos) = '\0';
  1425.                 maccur_noncurse_mode_show_str(str,
  1426.                                     &disp_row, &disp_col,
  1427.                                     NULL, FALSE, FALSE, FALSE);
  1428.                 *(str + disp_pos) = save_char;
  1429.  
  1430.                 maccur_noncurse_mode_show_str(str + disp_pos,
  1431.                                 &disp_row, &disp_col,
  1432.                                 &scroll_cnt, TRUE,
  1433.                                 add_newline_flag, cleareos_flag);
  1434.                 begin_at -= scroll_cnt * _maccur_cols;
  1435.             }
  1436.  
  1437.             if (single_char_flag && nchars > 0 && !string_ended_flag)
  1438.             {
  1439.                 string_ended_flag = TRUE;
  1440.                 rtn_val = nchars;
  1441.             }
  1442.         }
  1443.     }
  1444.  
  1445.     direct_curs_pos_row = disp_row;                                        /* Leave cursor where last update put it. */
  1446.     direct_curs_pos_col = disp_col;
  1447.  
  1448.     return rtn_val;
  1449. }
  1450.  
  1451. /********
  1452. **
  1453. **    maccur_printf:  Equivalent to printf.
  1454. **
  1455. **    Returns:
  1456. **        Results of vsprintf.
  1457. **
  1458. **
  1459. ********/
  1460.  
  1461. int    maccur_printf(
  1462. char *fmt,
  1463. ...
  1464. ) {
  1465.     va_list args;
  1466.     int rtn;
  1467.  
  1468.     if (screen_char_arry == NULL)
  1469.         maccur_init();
  1470.  
  1471.     va_start(args, fmt);
  1472.     rtn = vsprintf(_curses_prntw, fmt, args);
  1473.     va_end(args);
  1474.  
  1475.     if (rtn < 0) return rtn;
  1476.  
  1477.     maccur_noncurse_mode_show_str(_curses_prntw, &direct_curs_pos_row,
  1478.                                 &direct_curs_pos_col, NULL, TRUE,
  1479.                                 FALSE, FALSE);
  1480.  
  1481.     if (_maccur_io_sleep_dvsr > 0 && ++cpu_share_rot_cnt >= _maccur_io_sleep_dvsr)
  1482.     {
  1483.         maccur_cpu_share();
  1484.         cpu_share_rot_cnt = 0;
  1485.     }
  1486.  
  1487.     return rtn;
  1488. }
  1489.  
  1490. /********
  1491. **
  1492. **    maccur_puts:  Equivalent to puts.
  1493. **
  1494. **    Returns:
  1495. **        0 (success).
  1496. **
  1497. **
  1498. ********/
  1499.  
  1500. int maccur_puts(
  1501. char *str
  1502. ) {
  1503.     if (screen_char_arry == NULL)
  1504.         maccur_init();
  1505.  
  1506.     maccur_noncurse_mode_show_str(str, &direct_curs_pos_row,
  1507.                                 &direct_curs_pos_col, NULL, TRUE,
  1508.                                 TRUE, FALSE);
  1509.  
  1510.     if (_maccur_io_sleep_dvsr > 0 && ++cpu_share_rot_cnt >= _maccur_io_sleep_dvsr)
  1511.     {
  1512.         maccur_cpu_share();
  1513.         cpu_share_rot_cnt = 0;
  1514.     }
  1515.  
  1516.     return 0;
  1517. }
  1518.  
  1519. /********
  1520. **
  1521. **    maccur_putchar:  Equivalent to putchar.
  1522. **
  1523. **    Returns:
  1524. **        Character printed.
  1525. **
  1526. **
  1527. ********/
  1528.  
  1529. int maccur_putchar(
  1530. char c
  1531. ) {
  1532.     char str[2];
  1533.  
  1534.     if (screen_char_arry == NULL)
  1535.         maccur_init();
  1536.  
  1537.     str[0] = c;
  1538.     str[1] = '\0';
  1539.  
  1540.     maccur_noncurse_mode_show_str(str, &direct_curs_pos_row,
  1541.                                 &direct_curs_pos_col, NULL, TRUE,
  1542.                                 FALSE, FALSE);
  1543.  
  1544.     if (_maccur_io_sleep_dvsr > 0 && ++cpu_share_rot_cnt >= _maccur_io_sleep_dvsr)
  1545.     {
  1546.         maccur_cpu_share();
  1547.         cpu_share_rot_cnt = 0;
  1548.     }
  1549.  
  1550.     return c;
  1551. }
  1552.  
  1553. /********
  1554. **
  1555. **    maccur_scanf:  Equivalent to scanf.  Uses THINK C's non-portable _vsscanf.
  1556. **
  1557. **    Returns:
  1558. **        Results of _vsscanf.
  1559. **
  1560. **
  1561. ********/
  1562.  
  1563. int    maccur_scanf(
  1564. char *fmt,
  1565. ...
  1566. ) {
  1567.     va_list args;
  1568.     int rtn;
  1569.  
  1570.     if (screen_char_arry == NULL)
  1571.         maccur_init();
  1572.  
  1573.     maccur_noncurse_mode_getstr(_curses_prntw, _curses_prntw_size, FALSE);
  1574.  
  1575.     va_start(args, fmt);
  1576.     rtn = _vsscanf(_curses_prntw, fmt, args);
  1577.     va_end(args);
  1578.  
  1579.     return rtn;
  1580. }
  1581.  
  1582. /********
  1583. **
  1584. **    maccur_gets:  Equivalent to gets.
  1585. **
  1586. **    Returns:
  1587. **        Pointer to string argument (success).
  1588. **
  1589. **
  1590. ********/
  1591.  
  1592. char *maccur_gets(
  1593. char *str
  1594. ) {
  1595.  
  1596.     if (screen_char_arry == NULL)
  1597.         maccur_init();
  1598.  
  1599.     if (maccur_noncurse_mode_getstr(str, -1, FALSE) == EOF)
  1600.         return NULL;
  1601.  
  1602.     return str;
  1603. }
  1604.  
  1605. /********
  1606. **
  1607. **    maccur_getchar:  Equivalent to getchar.
  1608. **
  1609. **    Returns:
  1610. **        Character read or EOF.
  1611. **
  1612. **
  1613. ********/
  1614.  
  1615. int maccur_getchar(void)
  1616. {
  1617.     char str[2];
  1618.     int rtn;
  1619.  
  1620.     if (screen_char_arry == NULL)
  1621.         maccur_init();
  1622.  
  1623.     if (maccur_noncurse_mode_getstr(str, 2, TRUE) == EOF)
  1624.         rtn = EOF;
  1625.     else
  1626.         rtn = str[0];
  1627.  
  1628.     return rtn;
  1629. }
  1630.